﻿#ifndef _C_FMP4_APPENDER_H_
#define _C_FMP4_APPENDER_H_

//#include <iostream>
//#include <fstream>
//#include <cstdint>
//#include <stdio.h>
//#include <vector>

/* fmp4 Box 结构
ftyp
moov
moof
	mfhd
	traf
		tfhd
		tfdt
		trun
	traf
		tfhd
		tfdt
		trun
mdat
moof
	...
mdat
	...
...
mfra
	tfra
	tfra
*/
// 定义Box的结构体
struct Box 
{
	virtual ~Box() {
	}
	unsigned int size = 0;  // Box的大小
	char type[5] = {0};  // Box的类型
	char* buffer = nullptr;
};

struct TfdtBox : public Box
{
	unsigned int version = 0;
	unsigned long long baseMediaDecodeTime = 0;
	// 把相关字段从buffer读取到成员变量中
	bool parse();
	bool modifyBaseMediaDecodeTime(unsigned long long timeBase);
};

struct MfhdBox : public Box
{
	unsigned int version = 0;
	unsigned int sequenceNumber = 0;
	bool parse();
	bool modifySequenceNumber(unsigned int baseNumber);
};

struct TfhdBox : public Box
{
	unsigned int version = 0;
	unsigned int flags = 0;
	unsigned int trackId = 0;
	unsigned int sampleDescriptionIndex = 0;
	unsigned long long baseDataOffset = 0;
	unsigned int sampleDuration = 0;
	unsigned int sampleSize = 0;
	// 把相关字段从buffer读取到成员变量中
	bool parse();
	bool modifyBaseDataOffset(unsigned long long baseOffset);
};

struct TrunBox : public Box
{
	unsigned int version = 0;
	unsigned int flags = 0;
	unsigned int sampleCount = 0;
	unsigned int eachSampleDuration = 0;
	bool parse();
};

struct TrafBox : public Box
{
	TfhdBox tfhdBox;
	TfdtBox tfdtBox;
	TrunBox trunBox;
	bool parse();
};

struct MoofBox
{
	MoofBox(Box* box);
	~MoofBox();
	Box* moofBox = nullptr;
	unsigned long long moofOffset = 0;
	MfhdBox mfhdBox;
	TrafBox trafBox1;
	TrafBox trafBox2;
	bool parse();
};

struct TfraBox : public Box
{
	unsigned int version = 0;
	unsigned int trackId = 0;
	unsigned long long time = 0;
	unsigned long long moofOffset = 0;
	bool parse();
	bool modifyTime(unsigned long long baseTime);
	bool modifyMoofOffset(unsigned long long baseMoofOffset);
};

struct MfraBox
{
	MfraBox(Box* box);
	~MfraBox();
	Box* mfraBox = nullptr;
	TfraBox tfraBox1;
	TfraBox tfraBox2;
	bool parse();
};

class CFMP4Appender
{
public:
	CFMP4Appender();
	~CFMP4Appender();
	// return:
	// -1: unknown error
	// 0: success
	// -2: invalid anterior file
	// -3: open posterior file fail
	// -4: invalid posterior file
	// -5: append fail
	static int Append(const char* fmp4AnteriorSegmentFile, const char* fmp4PosteriorSegmentFile);
protected:
	static MoofBox* findLastMoofBox(const char* filePath);
	static MfraBox* getMfraBox(const char* filePath);
	static int ftruncateFile(const char* filePath, int length);
private:

};

#endif	// _C_FMP4_APPENDER_H_